#include "tem_sensor_drv.h"
// adc数值与温度对照表 数据的序号即为对应的温度
static const uint16_t g_ntcAdcTable[] = {
    3123, 3089, 3051, 3013, 2973, 2933, 2893, 2852, 2810, 2767,     //0   ~   9℃
    2720, 2681, 2637, 2593, 2548, 2503, 2458, 2412, 2367, 2321,     //10  ~  19℃
    2275, 2230, 2184, 2138, 2093, 2048, 2002, 1958, 1913, 1869,     //20  ~  29℃
    1825, 1782, 1739, 1697, 1655, 1614, 1573, 1533, 1494, 1455,     //30  ~  39℃
    1417, 1380, 1343, 1307, 1272, 1237, 1203, 1170, 1138, 1106,     //40  ~  49℃
    1081, 1045, 1016, 987,  959,  932,  905,  879,  854,  829,      //50  ~  59℃
    806,  782,  760,  738,  716,  696,  675,  656,  637,  618,      //60  ~  69℃
    600,  583,  566,  550,  534,  518,  503,  489,  475,  461,      //70  ~  79℃
    448,  435,  422,  410,  398,  387,  376,  365,  355,  345,      //80  ~  89℃
    335,  326,  316,  308,  299,  290,  283,  274,  267,  259,      //90  ~  99℃
};
// 对照表数据数量
#define NTC_TABLE_SIZE         (sizeof(g_ntcAdcTable) / sizeof(g_ntcAdcTable[0]))

// 把下标转成温度数据 下标是从0开始 温度可以为负值: 
//                在3123对应 - 10度的情况下 下标 - 10才是温度   本次下标-0就为温度
#define INDEX_TO_TEMP(index)   ((int32_t)(index))
#define MAX_BUF_SIZE         10
// 创建数组 保存转换的数值
static uint16_t g_temp10MplBuf[MAX_BUF_SIZE];
// 保存温度传感器滤波之后的结果
static float g_tempData;

static void GpioInit(void) {
    rcu_periph_clock_enable(RCU_GPIOC);
    gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_10MHZ, GPIO_PIN_3);
}

static void ADC0Init(void) {
    /* 使能时钟；*/
    rcu_periph_clock_enable(RCU_ADC0);
    /*重置adc*/
    adc_deinit(ADC0);
    /* 设置分频系数；*/
    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);// 6分频，120MHz / 6 = 20MHz
    /* 设置独立模式；*/
    adc_mode_config(ADC_MODE_FREE);
    /* 设置分辨率 12位 4095*/
    adc_resolution_config(ADC0, ADC_RESOLUTION_12B);
    /* 设置连续模式 */
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
    /* 设置扫描模式；*/
    adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);
    /* 设置数据对齐；*/
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    /* 常规通道个数 */
    adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);
    /* 常规规则 : 指定ADC 外设  通道的优先级  配置的 ADC 通道   采样时间(239个周期)*/
    adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_13, ADC_SAMPLETIME_239POINT5);
    /* 设置选择哪一个外部触发源: 软件触发*/
    adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
    /* 使能外部触发；*/
    adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
    /* 使能硬件滤波；*/
    adc_oversample_mode_config(ADC0, ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL16);
    adc_oversample_mode_enable(ADC0);
    /* 使能ADC；*/
    adc_enable(ADC0);
    /* 内部校准；*/
    DelayNus(50);
    adc_calibration_enable(ADC0);
    /* 触发一次*/
    adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}

/**
 * @desc  : 温度传感器驱动初始化
 * @date  : 2025-04-08
 * @author: AnRui
 * @note  : 包含GPIO和ADC初始化
 */
void TemSensorDrvInit(void) {
    GpioInit();
    ADC0Init();
}

/**
 * @desc  : 获取adc采样结果
 * @date  : 2025-04-09
 * @author: AnRui
 * @return: uint16_t
 * @note  : 因为是连续转换 所以获取的是最近一次转换的结果
 */
static uint16_t GetAdcVal(void) {
    /* 等待转换完成标志 连续采样16次完成后*/
    while (!adc_flag_get(ADC0, ADC_FLAG_EOC));
    /* 读取数据寄存器: 硬件滤波后的结果 */
    return (adc_regular_data_read(ADC0));
}

/**
 * @desc  : 根据采样值查找对应的温度值 并把温度数据提高10倍(精度由1变为0.1)
 * @date  : 2025-04-09
 * @author: AnRui
 * @param : adcVal - {参数说明}:
 * @return: uint16_t
 * @note  :
 */
static uint16_t AdcToTemp10Mpl(uint16_t adcVal) {
    // 返回最接近目标的下标(小于等于目标值) 不存在找不到的情况
    int32_t index = MathCalcDescBinarySearchNear(g_ntcAdcTable, NTC_TABLE_SIZE, adcVal);
    // 如果index=0 在进行-1 越界
    if (index == 0) {
        return 0;
    }
    // 正常的公式   x= index-1 +(g_ntcAdcTable[index - 1] - adcVal)/(g_ntcAdcTable[index - 1] - g_ntcAdcTable[index])
    // 首先上面包含了 adcVal等于g_ntcAdcTable[index]的情况
    // 并且上面的精度是1 要实现精度为0.1 所以 都扩大10倍 为下面的公式 
    uint16_t temp10Mpl = INDEX_TO_TEMP(index - 1) * 10 + (g_ntcAdcTable[index - 1] - adcVal) * 10 / (g_ntcAdcTable[index - 1] - g_ntcAdcTable[index]);
    return temp10Mpl;
}

/**
 * @desc  : 向缓冲区中放入本次转换的结果
 * @date  : 2025-04-09
 * @author: AnRui
 * @param : temp10Mpl - {参数说明}:
 * @note  :
 */
static void PushTemValToBuff(uint16_t temp10Mpl) {
    static uint32_t s_index = 0;
    g_temp10MplBuf[s_index] = temp10Mpl;
    s_index++;
    s_index %= MAX_BUF_SIZE;
}

/**
 * @desc  : 触发采样并更新结果
 * @date  : 2025-04-09
 * @author: AnRui
 * @note  :
 */
void TemSensorDrvProc(void) {
    // 记录转换次数 1s一次 135年才会溢出
    static uint16_t s_convertNum = 0;
    uint16_t    adcVal = GetAdcVal();
    uint16_t temp10Mpl = AdcToTemp10Mpl(adcVal);
    PushTemValToBuff(temp10Mpl);
    s_convertNum++;

    // 不足三次不可以 进行中位数运算
    if (s_convertNum < 3) {
        g_tempData = g_temp10MplBuf[0] / 10.0f;
        return;
    }
    // 如果转换的次数超过数组的长度 就取最大值 为接下来计算中位数做准备
    if (s_convertNum > MAX_BUF_SIZE) {
        s_convertNum = MAX_BUF_SIZE;
    }
    g_tempData = MathCalcTrimmedMean(g_temp10MplBuf, s_convertNum) / 10.0f;
}

/**
 * @desc  : 获取温度采集转换结果
 * @date  : 2025-04-09
 * @author: AnRui
 * @return: float
 * @note  :
 */
float GetTemSensorResult() {
    return g_tempData;
}
